/**
 ******************************************************************************
 * @file    uart.c
 * @author  hyseim software Team
 * @date    18-Aug-2023
 * @brief   This file provides all the tmp functions.
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2020 Hyseim. Co., Ltd.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "uart.h"
#include "common.h"


/** @addtogroup IM110GW_Driver
 * @{
 */

/** @defgroup UART
 * @brief UART driver modules
 * @{
 */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define TIMEOUT (0xFFFF)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
 * @brief  Initializes the UARTx peripheral according to the specified
 *         parameters in the UART_InitStruct.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  UART_InitStruct: pointer to a UART_InitTypeDef structure
 *         that contains the configuration information for the specified
 *         UART peripheral.
 * @return None
 */
uint8_t UART_Init(UART_t *UARTx, uint32_t UART_Clk, UART_Init_t *UART_InitStruct)
{
    /* NOTE:Configuration sequence:
        1.ASSI_DeInit(...);
        2.Configure MCR register:SIR mode,autoflow,loopback,modem;
        3.Configure DLF,DLL,DLH;
        4.Configure LCR;
        5.Configuring FIFO(optional)
        6.UART_IOmuxCfg(...);
        7.ASSI_Init(...);
    */
    uint32_t divider;

    UARTx->MCR = UART_InitStruct->UART_AutoFlowControl;

    divider = (UART_Clk + (UART_InitStruct->UART_BaudRate >> 1)) / UART_InitStruct->UART_BaudRate;
    UARTx->LCR = UART_LCR_DLAB;
    UARTx->DLF = divider & 0x0F;
    UARTx->DLL = (uint8_t)(divider >> 4);
    UARTx->DLH = (uint8_t)(divider >> 12);
    UARTx->LCR &= ~UART_LCR_DLAB;
    UARTx->LCR = UART_InitStruct->UART_WordLength | UART_InitStruct->UART_StopBits | UART_InitStruct->UART_Parity;

    if (UART_InitStruct->UART_FIFO_Enable == ENABLE) 
    {
        UART_FIFOCmd(UARTx, ENABLE);
    }
    else 
    {
        UART_FIFOCmd(UARTx, DISABLE);
    }
}

/**
 * @brief  Fills each UART_InitStruct member with its default value.
 * @param  UART_InitStruct: pointer to a UART_InitTypeDef structure
 *         which will be initialized.
 * @return None
 */
void UART_StructInit(UART_Init_t *UART_InitStruct)
{
    /* UART_InitStruct members default value */
    UART_InitStruct->UART_BaudRate = 115200;
    UART_InitStruct->UART_FIFO_Enable = DISABLE;
    UART_InitStruct->UART_AutoFlowControl = UART_AutoFlowControl_None;
    UART_InitStruct->UART_WordLength = UART_WordLength_8b;
    UART_InitStruct->UART_StopBits = UART_StopBits_One;
    UART_InitStruct->UART_Parity = UART_Parity_None;
}

/**
 * @brief  Write data to THR register or Tx FIFO.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  Data: the data to write.
 * @return None
 */
void UART_WriteData(UART_t *UARTx, uint16_t Data)
{
    UARTx->THR = Data;
}

/**
 * @brief  Read data from RBR register or Rx FIFO.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return The received data
 */
uint16_t UART_ReadData(UART_t *UARTx)
{
    return UARTx->RBR;
}

/**
 * @brief  Configure UARTx's Rx FIFO trigger threshold.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  Threshold: This parameter can be one of the following values:
 *         @arg @ref UART_RxFIFOThreshold_1
 *         @arg @ref UART_RxFIFOThreshold_4
 *         @arg @ref UART_RxFIFOThreshold_8
 *         @arg @ref UART_RxFIFOThreshold_14
 * @return None
 */
void UART_RxFIFOThresholdConfig(UART_t *UARTx, uint8_t Threshold)
{
    UARTx->SRT = (uint32_t)Threshold;
}

/**
 * @brief  Configure UARTx's Tx FIFO trigger threshold.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  Threshold: This parameter can be one of the following values:
 *         @arg @ref UART_TxFIFOThreshold_0
 *         @arg @ref UART_TxFIFOThreshold_2
 *         @arg @ref UART_TxFIFOThreshold_4
 *         @arg @ref UART_TxFIFOThreshold_8
 * @return None
 */
void UART_TxFIFOThresholdConfig(UART_t *UARTx, uint8_t Threshold)
{
    UARTx->STET = (uint32_t)Threshold;
}

/**
 * @brief  Enables or disables the UARTx's FIFO.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  NewState: new state of the FIFO.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void UART_FIFOCmd(UART_t *UARTx, FunctionalState_t NewState)
{
    if (NewState != DISABLE)
    {
        UARTx->SFE = 0x01;
    }
    else
    {
        UARTx->SFE = 0x00;
    }
}

/**
 * @brief  Reset the UART's Rx FIFO.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return None
 */
void UART_ResetRxFIFO(UART_t *UARTx)
{
    UARTx->SRR = UART_SRR_RFR;
}

/**
 * @brief  Reset the UART's Tx FIFO.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return None
 */
void UART_ResetTxFIFO(UART_t *UARTx)
{
    UARTx->SRR = UART_SRR_XFR;
}

/**
 * @brief  Force the serial out to spacing state or not.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  NewState: new state of the Break control bit.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void UART_ForceBreakCmd(UART_t *UARTx, FunctionalState_t NewState)
{
    if (NewState != DISABLE)
    {
        UARTx->SBCR = 0x01;
    }
    else
    {
        UARTx->SBCR = 0x00;
    }
}

/**
 * @brief  Enables or disables the UARTx's Programmable THRE Interrupt Mode.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  NewState: new state of the Programmable THRE Interrupt Mode.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void UART_ProgrammableTHREModeCmd(UART_t *UARTx, FunctionalState_t NewState)
{
    if (NewState != DISABLE)
    {
        UARTx->IER |= UART_IER_PTIME;
    }
    else
    {
        UARTx->IER &= ~UART_IER_PTIME;
    }
}

/**
 * @brief  Enables or disables the UARTx's interrupts.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  UART_IT: specifies the UART interrupt sources to be enabled or disabled.
 *         This parameter can be a combination of the following values:
 *         @arg @ref UART_IT_RDA
 *         @arg @ref UART_IT_THRE
 *         @arg @ref UART_IT_RLS
 *         @arg @ref UART_IT_MSI
 * @param  NewState: new state of the interrupts.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void UART_ITConfig(UART_t *UARTx, uint8_t UART_IT, FunctionalState_t NewState)
{
    if (NewState != DISABLE)
    {
        UARTx->IER |= UART_IT;
    }
    else
    {
        UARTx->IER &= ~UART_IT;
    }
}

/**
 * @brief  Get UARTx's Interrupt ID.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return Interrupt ID.
 */
uint8_t UART_GetIntID(UART_t *UARTx)
{
    return UARTx->IIR & UART_IIR_INTID_Msk;
}

/**
 * @brief  Checks whether the specified UART flag is set or not.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  UART_FLAG: specifies the flag to check.
 *         This parameter can be one of the following values:
 *         @arg @ref UART_FLAG_BUSY: Busy flag.
 *         @arg @ref UART_FLAG_TFNF: Transmit FIFO Not Full flag.
 *         @arg @ref UART_FLAG_TFE: Transmit FIFO Empty flag.
 *         @arg @ref UART_FLAG_RFNE: Receive FIFO Not Empty flag.
 *         @arg @ref UART_FLAG_RFF: Receive FIFO Full flag.
 * @return The new state of UART_FLAG (SET or RESET).
 */
FlagStatus_t UART_GetFlagStatus(UART_t *UARTx, uint32_t UART_FLAG)
{
    FlagStatus_t bitstatus = RESET;

    if ((UARTx->USR & UART_FLAG) != (uint32_t)RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}

/**
 * @brief  Get UARTx's Line status.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return UARTx's Line status.
 */
uint32_t UART_GetLineStatus(UART_t *UARTx)
{
    return UARTx->LSR;
}

/**
 * @brief  Get UARTx's Modem Status.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return UARTx's Modem Status.
 */
uint32_t UART_GetModemStatus(UART_t *UARTx)
{
    return UARTx->MSR;
}

/**
 * @brief  Control RTS Pin State.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  NewState: new state of the RTS Pin State.
 *         This parameter can be: ACTIVE or INACTIVE.
 * @return None
 */
void UART_ModemForceRtsPinState(UART_t *UARTx, SignalState_t NewState)
{
    if (NewState != INACTIVE)
    {
        UARTx->MCR |= UART_MCR_RTS;
    }
    else
    {
        UARTx->MCR &= ~UART_MCR_RTS;
    }
}

/**
 * @brief  waitint for THR register empty
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return None
 */
void UART_WaitSendFIFOEmpty(UART_t *UARTx)
{
    while(!((UARTx->LSR) & 0x20)){ ; }  
}

/**
 * @brief  Wait until the desired number of data is received.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  num: The number of data you want to receive cannot exceed the FIFO depth
 * @return None
 */
void UART_WaitReceiveFIFORFL(UART_t *UARTx, int num)
{
    while ((UARTx->RFL) != num);
}


/**
 * @brief  9bit Send address
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  addr: Send Address
 * @return None
 */
void UART_Set9BitTransmitAddress(UART_t *UARTx, uint8_t addr)
{
    UARTx->TAR = addr;
    UARTx->EXTLCR = UART_EXTLCR_WLS_E | UART_EXTLCR_ADDR_MATCH | UART_EXTLCR_SEND_ADDR;
}

/**
 * @brief  Enables or disables the UARTx's LoopBack Mode.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  NewState: new state of the LoopBack Mode.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void UART_LoopBackModeCmd(UART_t *UARTx, FunctionalState_t NewState)
{
  if (NewState != DISABLE) {
    UARTx->MCR |= UART_MCR_LB;
  }
  else {
    UARTx->MCR &= ~UART_MCR_LB;
  }
}

/**
 * @brief  Enables or disables the UARTx's IrDA SIR Mode.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  NewState: new state of the IrDA SIR Mode.
 *         This parameter can be: ENABLE or DISABLE.
 * @return None
 */
void UART_IrDACmd(UART_t *UARTx, FunctionalState_t NewState)
{
  if (NewState != DISABLE) {
    UARTx->MCR |= UART_MCR_SIRE;
  }
  else {
    UARTx->MCR &= ~UART_MCR_SIRE;
  }
}

/**
 * @brief  The 9bit address matching mode is configured.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @param  addr: the receive address
 * @return None
 */
void UART_Set9BitReceiveAddress(UART_t *UARTx, uint8_t addr)
{
    UARTx->RAR = addr;
    UARTx->EXTLCR = UART_EXTLCR_WLS_E | UART_EXTLCR_ADDR_MATCH;
}

/**
 * @brief  The configuration of sending 9bit data.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return None
 */
void UART_9bitDataModeConfig(UART_t *UARTx)
{
    UARTx->EXTLCR = UART_EXTLCR_WLS_E & (~UART_EXTLCR_ADDR_MATCH) & (~UART_EXTLCR_SEND_ADDR) | UART_EXTLCR_TRANSMIT_MODE;
}


/**
 * @brief  Clear the modem status interrupt flag.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return None
 */
void UART_ClearModemStatus(UART_t *UARTx)
{
    uint32_t msr = 0;

    msr = UARTx->MSR;
}

/**
 * @brief  Clear busy detection test interrupt.
 * @param  UARTx: Pointer to selected UART peripheral.
 *         This parameter can be one of the following values:
 *         UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7.
 * @return None
 */
void UART_ClearIntrBusyDetect(UART_t *UARTx)
{
    uint32_t usr = 0;
    usr = UARTx->USR;
}


/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */
